package linwen.wang.application.impl.v2;

import linwen.wang.application.OrderDetailService;
import linwen.wang.domain.AddressConvertMapper;
import linwen.wang.domain.OrderConvertMapper;
import linwen.wang.domain.ProductConvertMapper;
import linwen.wang.domain.UserConvertMapper;
import linwen.wang.entity.Address;
import linwen.wang.entity.Order;
import linwen.wang.entity.Product;
import linwen.wang.entity.User;
import linwen.wang.service.IAddressService;
import linwen.wang.service.IOrderService;
import linwen.wang.service.IProductService;
import linwen.wang.service.IUserService;
import linwen.wang.vo.AddressVO;
import linwen.wang.vo.OrderDetailVO;
import linwen.wang.vo.ProductVO;
import linwen.wang.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

@Service
public class OrderDetailServiceV2 implements OrderDetailService {
    @Autowired
    private IUserService userService;

    @Autowired
    private IProductService productService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IAddressService addressService;

    @Autowired
    private OrderConvertMapper orderConvertMapper;

    @Autowired
    private AddressConvertMapper addressConvertMapper;

    @Autowired
    private UserConvertMapper userConvertMapper;

    @Autowired
    private ProductConvertMapper productConvertMapper;


    @Override
    public List<? extends OrderDetailVO> getByUserId(Long userId) {
        List<Order> orders = this.orderService.getByUserId(userId);

        List<OrderDetailVOV2> orderDetailVOS =
                orders.stream()
                        .map(order -> new OrderDetailVOV2(orderConvertMapper.orderConvertOrderVO(order)))
                        .collect(toList());

        List<Long> userIds = orders.stream()
                .map(Order::getUserId)
                .collect(toList());
        List<User> users = this.userService.listByIds(userIds);
        Map<Long, User> userMap = users.stream()
                .collect(toMap(User::getId, Function.identity(), (a, b) -> a));
        for (OrderDetailVOV2 orderDetailVO : orderDetailVOS) {
            User user = userMap.get(orderDetailVO.getOrder().getUserId());
            UserVO userVO = userConvertMapper.userConvertUserVO(user);
            orderDetailVO.setUser(userVO);
        }

        List<Long> addressIds = orders.stream()
                .map(Order::getAddressId)
                .collect(toList());
        List<Address> addresses = this.addressService.listByIds(addressIds);
        Map<Long, Address> addressMap = addresses.stream()
                .collect(toMap(Address::getId, Function.identity(), (a, b) -> a));
        for (OrderDetailVOV2 orderDetailVO : orderDetailVOS) {
            Address address = addressMap.get(orderDetailVO.getOrder().getAddressId());
            AddressVO addressVO = addressConvertMapper.addressConvertAddressVO(address);
            orderDetailVO.setAddress(addressVO);
        }

        List<Long> productIds = orders.stream()
                .map(Order::getProductId)
                .collect(toList());
        List<Product> products = this.productService.listByIds(productIds);
        Map<Long, Product> productMap = products.stream()
                .collect(toMap(Product::getId, Function.identity(), (a, b) -> a));
        for (OrderDetailVOV2 orderDetailVO : orderDetailVOS) {
            Product product = productMap.get(orderDetailVO.getOrder().getProductId());
            ProductVO productVO = productConvertMapper.productConvertProductVO(product);
            orderDetailVO.setProduct(productVO);
        }
        return orderDetailVOS;
    }
}